// #pragma once
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , server(new MyTcpServer)
    , socket(nullptr)
    // , thread_count(0)
{
    ui->setupUi(this);
    server->listen(QHostAddress::AnyIPv4, PORT);

    // 客户端发起连接，服务器发出信号(这里是主线程)，newConnection 的触发在调用 incomingConnection 函数之后触发
    // 注意以上两种信号不能同时使用，会导致程序崩溃
    // connect(server, &QTcpServer::newConnection, this, &Widget::new_client_handler);

    // 链接子线程中连接客户消息的信号函数
    // connect(server, &MyTcpServer::get_my_client, this, &Widget::connet_info_slot);

    // 连接子 server 中消息的函数
    connect(server, &MyTcpServer::send_message_to_widget_signal, this, &Widget::thread_new_info_slot);

    // 连接显示线程数函数
    connect(server, &MyTcpServer::send_thread_count_signal, this, &Widget::show_thread_slot);

    // 连接显示子线程客户端信息函数
    // connect(server, &MyTcpServer::show_connect_info_signal, this, &Widget::connet_info_slot);
}

Widget::~Widget()
{
    delete ui;
}


// void Widget::connet_info_slot()
// {
//     // 显示链接客户端地址与端口文本
//     QHostAddress client_ip = server->get_my_client().back()->get_client_info()->client_ip;
//     quint16      client_port = server->get_my_client().back()->get_client_info()->client_port;
//     qDebug() << client_ip << client_port;
//     ui->ip_lineEdit->setText(client_ip.toString());
//     ui->port_lineEdit->setText(QString::number(client_port));
// }

void Widget::thread_new_info_slot()
{
    QString curTime = QTime::currentTime().toString("[hh:mm:ss] ");
    auto message_struct = server->get_current_message();
    QString client_message = message_struct->current_message;

    // ui 显示客户端连接信息
    // 显示链接客户端地址与端口文本
    QHostAddress client_ip = message_struct->client_ip;
    quint16      client_port = message_struct->client_port;
    qDebug() << client_ip << client_port;
    ui->ip_lineEdit->setText(client_ip.toString());
    ui->port_lineEdit->setText(QString::number(client_port));

    // ui 显示客户端消息
    ui->textEdit->append(curTime + " " + client_ip.toString() + " " + QString::number(client_port) + ":\n    " + client_message);

    // 转发消息给其他所有客户端
    auto clients = server->get_my_client();
    for (auto client : clients)
    {
        socket = client.first->get_client_socket();
        if (socket && (client_ip != socket->peerAddress() || client_port != socket->peerPort()))
        {   // 本来应该是好友间的转发，但是这里写全部转发，这种实际只用一个 socket 就行
            QString forward_message = client_ip.toString() + " " + QString::number(client_port) + "消息：\n" + client_message;
            QByteArray byte_array(forward_message.toUtf8().data());
            // byte_array.append(QByteArray a) 方法同上
            socket->write(byte_array);      // 写入到套接字
            socket->waitForBytesWritten();  // 等待数据发送完成

            // client.first->send_message_slot(&byte_array);
        }
    }
    // socket = nullptr;
}


void Widget::show_thread_slot()
{
    ui->thread_lineEdit->setText(QString::number(server->get_thread_count()));
}


// 客户端
// void Widget::new_client_handler()   // 主线程中显示
// {
//     // 与客户端建立 TCP 链接，注意下面的 socket 保存的是客户端的端口
//     socket = server->nextPendingConnection();   // socket 不能跨线程使用
//     /* socket 的本质是一个文件描述符，简言之是一个整数（指针） */

//     // 启动线程，这里将会在主线程中启动
//     // thread = new MyThread(socket);      // 线程对象
//     // my_client->moveToThread(thread);    // 移动到线程中
//     // thread->start();

//     ui->thread_lineEdit->setText(QString::number(++thread_count));

//     // connect(this, SIGNAL(Widget::signal_to_thread()), my_client, SLOT(ClientHandle::working()));
//     // emit signal_to_thread();

//     // 链接信号函数，这样用于显示客户端消息
//     // connect(thread, &MyThread::sand_to_widget, this, &Widget::accept_thread_info_slot);

//     // 获取客户端地址和端口号
//     client_ip   = socket->peerAddress();
//     client_port = socket->peerPort();
//     qDebug() << "连接端口" << client_port;

//     // 显示链接客户端地址与端口文本
//     ui->ip_lineEdit->setText(client_ip.toString());
//     ui->port_lineEdit->setText(QString::number(client_port));

//     // 服务器收到客户端发送的消息，socket 发出 readyRead 信号，手动连接槽函数
//     // connect(socket, &QTcpSocket::readyRead, this, &Widget::client_massage_slots);
// }


// void Widget::accept_thread_info_slot(QByteArray*& thread_byte_array)
// {   // 这里的 thread_byte_array 就是 MyThread::sand_to_widget(QByteArray*& thread_byte_array) 的参数 thread_byte_array
//     // ui 显示客户端消息
//     QString curTime = QTime::currentTime().toString("[hh:mm:ss] ");
//     ui->textEdit->append(curTime + QString::number(client_port) + ":\n    " + QString(*thread_byte_array));
// }


/*void Widget::client_massage_slots()
{   // 一种显示客户端消息的方法
    // 获取信号的发出者
    socket = (QTcpSocket*)sender();

    QString curTime = QTime::currentTime().toString("[hh:mm:ss] ");

    // 显示接收消息
    // message += QString::number(client_port);
    // message += ":\n    ";
    // // qDebug() << "消息内容：" << message;
    // message += QString(socket->readAll() + "\n");
    ui->textEdit->append(curTime + QString::number(client_port) + ":\n    " + QString(socket->readAll())); // readAll() 返回 QByteArray
    // qDebug() << "服务器错误信息：" << server->errorString();
}*/


void Widget::on_send_pushButton_clicked()
{
    // socket = new QTcpSocket;
    auto clients = server->get_my_client();
    bool one_message = false;
    for (auto client : clients)
    {   // 遍历所有客户端，发送消息
        socket = client.first->get_client_socket();
        if (socket)
        {
            QString curTime = QTime::currentTime().toString("[hh:mm:ss] ");
            QString current_input = ui->send_textEdit->toPlainText();
            QByteArray byte_array(current_input.toUtf8().data());
            // byte_array.append(QByteArray a) 方法同上
            socket->write(byte_array);      // 写入到套接字
            socket->waitForBytesWritten();  // 等待数据发送完成

            // 消息框显示记录
            if (!one_message)
            {
                ui->textEdit->append(curTime + "本服务器:\n    " + current_input);
                one_message = true;
            }
        }
        else
        {
            ui->textEdit->append("本服务器:\n    没有客户端在线，消息发送失败");
        }
    }
    // socket = nullptr;
    // 清空输入
    ui->send_textEdit->clear();
}


void Widget::on_disconnect_pushButton_clicked()
{
    this->close();
}

